#ifndef _NET_H
#define _NET_H

#define CONN_MAGIC_FDMSG         0x00010000   //fd传输
#define CONN_FD_REQUEST          0x00110000
#define CONN_FD_HANDLE           0x00210000
#define CONN_MAGIC_CMD           0x000f0000   //执行命令
#define CONN_CMD_STATUS          0x001f0000
#define CONN_CMD_START           0x002f0000
#define CONN_CMD_STOP            0x004f0000  
#define CONN_CMD_SHUTDOWN        0x008f0000   //关机命令


#define CONN_FDKIND_REG          0x00000001    //reg file fd
#define CONN_FDKIND_CHR          0x00000002    //char device
#define CONN_FDKIND_BLK          0x00000004    //block device
#define CONN_FDKIND_FIFO         0x00000008    //fifo fd 
#define CONN_FDKIND_SOCK         0x00000010    //socket fd 

#define CONN_MAGIC_INOTIFY       0x000a0000    //通知机制
#define CONN_INOTIFY_READY       0x001a0000    //就绪
#define CONN_INOTIFY_EXIT        0x002a0000    //退出

#define MAX_FDS  16
// 文件描述符类型
#define MSG__PEEK MSG_PEEK
#define MSGCMSG_CLOEXEC MSG_CMSG_CLOEXEC
#define SOCK__STREAM  SOCK_STREAM
#define SOCK__DGRAM   SOCK_DGRAM

#ifdef SIGINOTIFY
    #include <signal.h>
    #define sig_inotify(ppid,pid) sigqueue(ppid,SIGRTMIN+1,(union sigval)pid)
#else
    #define sig_inotify(ppid,pid)
#endif

#define CONN_SIGNAL_BASE         (SIGRTMIN+2) //信号基数
#define CONN_SIGNAL_READY        (CONN_SIGNAL_BASE+0) //进程就绪信号
#define CONN_SIGNAL_EXIT         (CONN_SIGNAL_BASE+1) //进程退出信号
#define CONN_SIGNAL_INOTIFY      (CONN_SIGNAL_BASE+2) //inotify信号

#define log(stream,fmt,...)    fprintf(stream,"[%s]: " fmt, "INFO", ##__VA_ARGS__)

struct Iovec{
    void *iov_base;
    size_t iov_len;
};


int listen_from(const char* addr_str,int type,int backlog);
int connect_to(const char *addr_str,int type,int timeout_sec);
int send_multiple_fds(int sock_fd, const int *fds, int fd_count, const char *data,size_t data_len,int flag);
int recv_multiple_fds(int sock_fd, int *received_fds, char *out_data,int flag);


int fd_handle(char *sockpath,char *msg);
int inotify(const char *path,void *info,size_t n);

// http status code
typedef enum {
    HTTP_STATUS_OK=200,
    HTTP_STATUS_CREATED=201,
    HTTP_STATUS_NO_CONTENT=204,
    HTTP_STATUS_MOVED_PERMANENTLY=301,
    HTTP_STATUS_FOUND=302,
    HTTP_STATUS_BAD_REQUEST=400,
    HTTP_STATUS_AUTH_REQUIRED=401,
    HTTP_STATUS_FORBIDDEN=403,
    HTTP_STATUS_NOT_FOUND=404,
    HTTP_STATUS_METHOD_NOT_ALLOWED=405,
    HTTP_STATUS_INTERNAL_SERVER_ERROR=500
} HTTP_STATUS_CODE;

typedef enum {
    HTTP_METHOD_GET=0,
    HTTP_METHOD_POST,
    HTTP_METHOD_PUT,
    HTTP_METHOD_DELETE,
    HTTP_METHOD_HEAD,
    HTTP_METHOD_OPTIONS,
    HTTP_METHOD_TRACE,
    HTTP_METHOD_CONNECT
} HTTP_METHOD;

typedef enum {
    HTTP_VERSION_1_0=0,
    HTTP_VERSION_1_1,
    HTTP_VERSION_2_0,
    HTTP_VERSION_3_0
} HTTP_VERSION;

typedef enum {
    HTTP_RESPONSE_STATUS_OK=200,
    HTTP_RESPONSE_STATUS_CREATED=201,
    HTTP_RESPONSE_STATUS_NO_CONTENT=204,
    HTTP_RESPONSE_STATUS_MOVED_PERMANENTLY=301,
    HTTP_RESPONSE_STATUS_FOUND=302,
    HTTP_RESPONSE_STATUS_BAD_REQUEST=400,
    HTTP_RESPONSE_STATUS_AUTH_REQUIRED=401,
    HTTP_RESPONSE_STATUS_FORBIDDEN=403,
    HTTP_RESPONSE_STATUS_NOT_FOUND=404,
    HTTP_RESPONSE_STATUS_METHOD_NOT_ALLOWED=405,
    HTTP_RESPONSE_STATUS_INTERNAL_SERVER_ERROR=500
}HTTP_RESPONSE_STATUS;


// http请求struct
typedef struct {
    char method[10];
    char url[256];
    char version[11];
    char headers[1024];
    char body[2790];
} HTTP_REQUEST;

// http响应struct
typedef struct {
    char version[11];
    HTTP_STATUS_CODE status_code;
    char status_msg[100];
    char headers[1024];
    char body[2790];
} HTTP_RESPONSE;

int serialize_http_request_v1(const HTTP_REQUEST *req,char *request,int maxlen);
int unserialize_http_request_v1( const char *request,HTTP_REQUEST *req);
int serialize_http_response_v1(const HTTP_RESPONSE *res,char *response,int maxlen);
int unserialize_http_response_v1( const char *response,HTTP_RESPONSE *res);
int send_http_request_v1(int sockfd,const HTTP_REQUEST *req,const int *fds, int fd_count);
int recv_http_request_v1(int sockfd,HTTP_REQUEST *req,int *received_fds);  
int send_http_response_v1(int sockfd,const HTTP_RESPONSE *res,const int *fds, int fd_count);
int recv_http_response_v1(int sockfd,HTTP_RESPONSE *res,int *received_fds);

#endif
